// 用法 new Compile(el, vm)

class Compile{
    constructor(el, vm){
        //要遍历的宿主节点
        this.$el = document.querySelector(el)
        this.$vm = vm;

        //编译
        if(this.$el){
            //转换内部内容片断 Fragment
            this.$fragment  = this.node2Fragment(this.$el)
            //执行编译部分
            this.compile(this.$fragment);
            //将编译完的结果追加到$el
            this.$el.appendChild(this.$fragment)
        }
    }
    //将宿主中代码片断拿出来遍历。更高效
    node2Fragment(el){
        const frag = document.createDocumentFragment();
        //将el中多有子元素搬家至frag中
        let child;
        while(child = el.firstChild){
            frag.appendChild(child);
        }
        return frag;
    }
    compile(el){
        const childNodes = el.childNodes;
        Array.from(childNodes).forEach(node => {
            //类型判断
            if(this.isElement(node)){
                // console.log('元素' + node.nodeName)
                // 查找 k-，@  :
                const nodeAttrs = node.attributes;
                Array.from(nodeAttrs).forEach(attr=>{
                    const attrName = attr.name;
                    const exp = attr.value;
                    if(this.isDirective(attrName)){
                        //k-...
                        const dir = attrName.substring(2)
                        //执行指令
                        this[dir] && this[dir](node,this.$vm,exp);
                    }
                    if(this.isEvent(attrName)){
                    }
                })
            }else if(this.isInterpolation(node)){
                //console.log('文本' + node.textContent)
                this.compileText(node)
            }
            //递归子节点
            if(node.childNodes && node.childNodes.length>0){
                this.compile(node)
            }
        })
    }
    compileText(node){
        this.update(node,this.$vm,RegExp.$1,'text')
        // console.log(RegExp.$1);
        // node.textContent = this.$vm.$data[RegExp.$1]
    }

    //更新函数
    update(node, vm, exp, dir){
        const updateFn = this[dir+'Updater'];
        //初始化
        updateFn && updateFn(node, vm[exp]);
        //依赖收集
        new Watcher(vm, exp,function(value){
            updateFn && updateFn(node, value);
        })
    }
    text(node,vm,exp){
        this.update(node,vm,exp,'text')
    }
    textUpdater(node, value){
        node.textContent = value
    }
    isDirective(attr){
        return attr.indexOf('k-') == 0;
    }
    isEvent(){

    }
    eventHandler(node, vm, exp, dir) { 
        let fn = vm.$options.methods && vm.$options.methods[exp] 
        if (dir && fn) { 
            node.addEventListener(dir, fn.bind(vm), false)
        } 
    }

    isElement(node){
        return node.nodeType === 1;
    }
    isInterpolation(node){
        return node.nodeType === 3 && /\{\{(.*)\}\}/.test(node.textContent);
    }
}